package com.zoomlion.core.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;



/**
 * <h6>设计说明：</h6>
 * <ol>
 * 通用DAO实现类，系统整合Hibernate和iBATIS的通用操作，在没有特殊需求的情况下，业务类不需要编写自己的DAO类。
 * </ol>
 * <ol>
 * 注意：在一个事务中可以同时使用Hibernate和iBATIS进行操作，事务的整合由springframework完成，不会造成事务错误。
 * </ol>
 * <h6>实现说明：</h6> <li>
 * 此类提供的是HibernateTemplate的Delagation方法，即将HibernateTemplate原封不动的放到此类中 ，并添加了一些分页处理的方法</li> <li>
 * 此类还将SqlMapClientDaoSupport的实现Copy过来，并且生成了SqlMapClientTemplate的代理方法</li> <li>
 * 注意：由于HibernateTemplate和SqlMapClientTemplate有些方法冲突，这时都是保留HibernateTemplate的方法， 对SqlMapClientTemplate的处理是在
 * 其方法后面添加ByIbatis的后缀以便区分，这里主要是delete和update这两类方法名的冲突。</li>
 * 
 * @author
 */
@Repository("commonDAO")
public class CommonDAO extends HibernateDaoSupport {
	// ///////////////////////////////////////////////////////////////////////////////////////////
	// 下面是HibernateTemplate的代理方法，并添加了部分用于分页用的Hibernate扩展函数
	// ///////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * 使用HSQL语句直接增加、更新、删除实体 queryString update sql
	 */
	@Resource(name="sessionFactory")
	 public void setSuperSessionFactory(SessionFactory sessionFactory){
        super.setSessionFactory(sessionFactory);
    }
	protected Logger logger = Logger.getLogger(getClass());
	public int bulkUpdate(String queryString) throws DataAccessException {
		return getHibernateTemplate().bulkUpdate(queryString);
	}

	/**
	 * 使用HSQL语句直接增加、更新、删除实体 queryString update sql, value 值
	 */
	public int bulkUpdate(String queryString, Object value) throws DataAccessException {
		return getHibernateTemplate().bulkUpdate(queryString, value);
	}

	/**
	 * 使用HSQL语句直接增加、更新、删除实体 queryString update sql, value 值数组
	 */
	public int bulkUpdate(String queryString, Object[] values) throws DataAccessException {
		return getHibernateTemplate().bulkUpdate(queryString, values);
	}

	/**
	 * 按照sql-query更新
	 */
	public void updateByNameQuery(final String queryString, final String paramName, final Object value) {
		getHibernateTemplate().execute(new HibernateCallback<Object>() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				applyNamedParameterToQuery(query, paramName, value);
				query.executeUpdate();
				return null;
			}
		});
	}

	/**
	 * 按照sql-query更新
	 * 
	 * @param queryString
	 * @param paramNames
	 * @param values
	 */
	public void updateByNameQuery(final String queryString, final String[] paramNames, final Object[] values) {
		getHibernateTemplate().execute(new HibernateCallback<Object>() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				for (int i = 0; i < values.length; i++) {
					applyNamedParameterToQuery(query, paramNames[i], values[i]);
				}
				query.executeUpdate();
				return null;
			}
		});
	}

	/**
	 * 从 Session cache 删除所有的对象
	 * 
	 * @throws DataAccessException
	 */
	public void clear() throws DataAccessException {
		getHibernateTemplate().clear();
	}

	/**
	 * 关闭检索返回的 Iterator
	 * 
	 * @param it
	 * @throws DataAccessException
	 */
	@SuppressWarnings("rawtypes")
	public void closeIterator(Iterator it) throws DataAccessException {
		getHibernateTemplate().closeIterator(it);
	}

	/**
	 * 在Session cache检查有无entity
	 * 
	 * @param entity
	 * @return boolean
	 * @throws DataAccessException
	 */
	public boolean contains(Object entity) throws DataAccessException {
		return getHibernateTemplate().contains(entity);
	}

	/**
	 * 删除并提供加锁功能
	 * 
	 * @param entity
	 * @param lockMode
	 *            锁类别
	 * @throws DataAccessException
	 */
	public void delete(Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().delete(entity, lockMode);
	}

	/**
	 * 删除
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void delete(Object entity) throws DataAccessException {
		getHibernateTemplate().delete(entity);
	}

	/**
	 * 根据Class和serializable删除记录
	 * 
	 * @param entity
	 * @param id
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void delete(Class clazz, Long id) {
		getHibernateTemplate().delete(getHibernateTemplate().get(clazz, id));
	}

	/**
	 * 根据实体名删除记录并加锁
	 * 
	 * @param entityName
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void delete(String entityName, Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().delete(entityName, entity, lockMode);
	}

	/**
	 * 根据实体名删除实体
	 * 
	 * @param entityName
	 * @param entity
	 * @throws DataAccessException
	 */
	public void delete(String entityName, Object entity) throws DataAccessException {
		getHibernateTemplate().delete(entityName, entity);
	}

	/**
	 * 批量删除
	 * 
	 * @param entities
	 * @throws DataAccessException
	 */
	@SuppressWarnings("rawtypes")
	public void deleteAll(Collection entities) throws DataAccessException {
		getHibernateTemplate().deleteAll(entities);
	}

	/**
	 * 从Session cache中删除entity
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void evict(Object entity) throws DataAccessException {
		getHibernateTemplate().evict(entity);
	}

	/**
	 * 执行action操作
	 * 
	 * @param action
	 * @return
	 * @throws DataAccessException
	 */
	public Object execute(HibernateCallback<Object> action) throws DataAccessException {
		return getHibernateTemplate().execute(action);
	}

	/**
	 * 执行查询操作
	 * 
	 * @param action
	 * @return
	 * @throws DataAccessException
	 */
	public List executeFind(HibernateCallback action) throws DataAccessException {
		return getHibernateTemplate().executeFind(action);
	}

	/**
	 * hibernate执行操作不创建新session
	 * 
	 * @param action
	 * @return
	 */
	public Object executeWithNativeSession(HibernateCallback action) {
		return getHibernateTemplate().executeWithNativeSession(action);
	}

	/**
	 * hibernate执行操作创建新session
	 * 
	 * @param action
	 * @return
	 */
	public Object executeWithNewSession(HibernateCallback action) {
		return getHibernateTemplate().executeWithNewSession(action);
	}

	/**
	 * 使用带参数的HSQL语句检索数据
	 * 
	 * @param queryString
	 *            hql 语句
	 * @param firstResult
	 *            开始
	 * @param maxResults
	 *            每页数
	 * @return
	 * @throws DataAccessException
	 */
	public List find(String queryString, int firstResult, int maxResults) throws DataAccessException {
		Query query = this.getSession().createQuery(queryString);
		query.setFirstResult(firstResult);
		query.setMaxResults(maxResults);
		return query.list();
	}

	/**
	 * 使用带参数的HSQL语句进行分页查询
	 * @param queryString
	 *        HQL语句
	 * @param values
	 *        语句中问号?对应的参数
	 * @param firstResult
	 *        开始数
	 * @param maxResults
	 *        每页数
	 * @return
	 * @throws DataAccessException
	 */
	public List find(String queryString, Object[] values, int firstResult, int maxResults) throws DataAccessException {
		Query query = this.getSession().createQuery(queryString);
		if ( values != null ){
			for ( int i = 0; i < values.length; i ++)
				query.setParameter(i, values[i]);
		}
		query.setFirstResult(firstResult);
		query.setMaxResults(maxResults);
		return query.list();
	}

	/**
	 * 使用带参数的HSQL语句检索数据
	 * 
	 * @param queryString
	 * @param value
	 * @return
	 * @throws DataAccessException
	 */
	public List find(String queryString, Object value) throws DataAccessException {
		return getHibernateTemplate().find(queryString, value);
	}

	/**
	 * 使用带参数的HSQL语句检索数据
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 * @throws DataAccessException
	 */
	public List find(String queryString, Object[] values) throws DataAccessException {
		return getHibernateTemplate().find(queryString, values);
	}

	/**
	 * 使用HSQL语句检索数据
	 * 
	 * @param queryString
	 * @return
	 * @throws DataAccessException
	 */
	public List find(String queryString) throws DataAccessException {
		return getHibernateTemplate().find(queryString);
	}

	/**
	 * 使用指定的检索标准检索数据并分页返回数据
	 * 
	 * @param criteria
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws DataAccessException
	 */
	public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) throws DataAccessException {
		return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
	}

	/**
	 * 使用指定的检索标准检索数据
	 * 
	 * @param criteria
	 * @return
	 * @throws DataAccessException
	 */
	public List findByCriteria(DetachedCriteria criteria) throws DataAccessException {
		return getHibernateTemplate().findByCriteria(criteria);
	}

	/**
	 * 使用指定的检索标准检索数据并分页
	 * 
	 * @param exampleEntity
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws DataAccessException
	 */
	public List findByExample(Object exampleEntity, int firstResult, int maxResults) throws DataAccessException {
		return getHibernateTemplate().findByExample(exampleEntity, firstResult, maxResults);
	}

	/**
	 * 使用指定的检索标准检索数据
	 * 
	 * @param exampleEntity
	 * @return
	 * @throws DataAccessException
	 */
	public List findByExample(Object exampleEntity) throws DataAccessException {
		return getHibernateTemplate().findByExample(exampleEntity);
	}

	/**
	 * 使用指定的检索标准检索数据并分页
	 * 
	 * @param entityName
	 * @param exampleEntity
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws DataAccessException
	 */
	public List findByExample(String entityName, Object exampleEntity, int firstResult, int maxResults)
			throws DataAccessException {
		return getHibernateTemplate().findByExample(entityName, exampleEntity, firstResult, maxResults);
	}

	/**
	 * 使用指定的检索标准检索数据
	 * 
	 * @param entityName
	 * @param exampleEntity
	 * @return
	 * @throws DataAccessException
	 */
	public List findByExample(String entityName, Object exampleEntity) throws DataAccessException {
		return getHibernateTemplate().findByExample(entityName, exampleEntity);
	}

	/**
	 * 查询实体对象列表
	 * 
	 * @param entityClass
	 * @param firstResult
	 * @param maxResults
	 * @return
	 */
	public <T> List<T> getList(final Class<T> entityClass, final int firstResult, final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback<Object>() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery("from " + entityClass.getName());
				return query.setFirstResult(firstResult).setMaxResults(maxResults).list();
			}
		});
	}

	/**
	 * 根据NamedQuery查询记录，支持分页查询
	 * 
	 * @param queryString
	 *            hbm.xml文件中配置的HQL或SQL查询语句
	 * @param firstResult
	 *            起始记录index
	 * @param maxResults
	 *            最大返回记录数
	 * @return
	 */
	public List findByNamedQuery(final String queryString, final int firstResult, final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				return session.getNamedQuery(queryString).setFirstResult(firstResult).setMaxResults(maxResults).list();
			}
		});
	}

	/**
	 * 根据NamedQuery查询记录，其中查询条件占位符为?，支持分页查询
	 * 
	 * @param queryString
	 *            hbm.xml文件中配置的HQL或SQL查询语句
	 * @param value
	 *            查询条件
	 * @param firstResult
	 *            起始记录index
	 * @param maxResults
	 *            最大返回记录数
	 * @return
	 */
	public List findByNamedQuery(final String queryString, final Object value, final int firstResult,
			final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
				query.setParameter(0, value);
				return query.list();
			}
		});
	}

	/**
	 * 根据NamedQuery查询记录，其中查询条件占位符为?，支持分页查询
	 * 
	 * @param queryString
	 *            hbm.xml文件中配置的HQL或SQL查询语句
	 * @param values
	 *            查询条件
	 * @param firstResult
	 *            起始记录index
	 * @param maxResults
	 *            最大返回记录数
	 * @return
	 */
	public List findByNamedQuery(final String queryString, final Object[] values, final int firstResult,
			final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
				for (int i = 0; i < values.length; i++) {
					query.setParameter(i, values[i]);
				}
				return query.list();
			}
		});
	}

	/**
	 * 根据NamedQuery查询记录，其中查询条件占位符为:，支持分页查询
	 * 
	 * @param queryString
	 *            hbm.xml文件中配置的HQL或SQL查询语句
	 * @param paramName
	 *            查询条件占位符名称
	 * @param value
	 *            查询条件值
	 * @param firstResult
	 *            起始记录index
	 * @param maxResults
	 *            最大返回记录数
	 * @return
	 */
	public List findByNamedQueryAndNamedParam(final String queryString, final String paramName, final Object value,
			final int firstResult, final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
				query.setParameter(paramName, value);
				return query.list();
			}
		});
	}

	/**
	 * 根据NamedQuery查询记录，其中查询条件占位符为:，支持分页查询
	 * 
	 * @param queryString
	 *            hbm.xml文件中配置的HQL或SQL查询语句
	 * @param paramName
	 *            查询条件占位符名称
	 * @param value
	 *            查询条件值
	 * @param firstResult
	 *            起始记录index
	 * @param maxResults
	 *            最大返回记录数
	 * @return
	 */
	public List findByNamedQueryAndNamedParam(final String queryString, final String[] paramNames,
			final Object[] values, final int firstResult, final int maxResults) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
				for (int i = 0; i < values.length; i++) {
					query.setParameter(paramNames[i], values[i]);
				}
				return query.list();
			}
		});
	}

	/**
	 * 获取单个实体类型的记录条数
	 * 
	 * @param entityClass
	 * @return
	 */
	public Long getCount(final Class entityClass) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery("select count(*) from " + entityClass.getName());
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 求和函数，用于抓取资料库内某一字段值并求和。支持条件查询
	 * 
	 * @param entityClass
	 *            POJO对象
	 * @param property
	 *            求和字段
	 * @param cond
	 *            条件语句
	 * @return
	 */
	public Long getSum(final Class entityClass, final String property, final String cond) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				String condition = StringUtils.isBlank(cond) ? "1=1" : cond;
				String hql = "select nvl(sum(" + property + "),0) from " + entityClass.getName() + " where "
						+ condition;
				if (logger.isDebugEnabled()) {
					logger.debug("取得" + entityClass + "类型的" + property + "字段总和sql为：" + hql);
				}
				Query query = session.createQuery(hql);
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 获取单个实体类型的记录条数
	 * 
	 * @param entityClass
	 * @return
	 */
	public Long getCount(final Class entityClass, final String paramName, final Object value) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery("select count(*) from " + entityClass.getName());
				query.setParameter(paramName, value);
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 获取单个实体类型的记录条数
	 * 
	 * @param entityClass
	 * @return
	 */
	public Long getCount(final Class entityClass, final String[] paramNames, final Object[] values) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery("select count(*) from " + entityClass.getName());
				for (int i = 0; i < values.length; i++) {
					query.setParameter(paramNames[i], values[i]);
				}
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 得到一条件下的记录数量
	 * 
	 * @param queryString
	 * @param paramName
	 * @param value
	 * @return
	 */
	public Long getCountByNamedParam(final String queryString, final String paramName, final Object value) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				query.setParameter(paramName, value);
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 得到一条件下的记录数量
	 * 
	 * @param queryString
	 * @return
	 */
	public Long getCountByQueryString(final String queryString) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 得到查询对应的记录数量
	 * @param queryString
	 *        SQL语句
	 * @param values
	 *        SQL语句中问号?对应的参数值
	 * @return
	 */
	public Long getCountByQueryString(final String queryString, final Object[] values) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				if ( values != null){
					for ( int i = 0; i < values.length; i ++){
						query.setParameter(i, values[i]);
					}
				}
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 得到一条件下的记录数量
	 * 
	 * @param queryString
	 * @return
	 */
	public Long getCountByQueryString(final String queryString, final String paramName, final Object value) {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				query.setParameter(paramName, value);
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 得到一条件下的记录数量
	 * 
	 * @param queryString
	 * @param paramNames
	 * @param values
	 *            对象数组
	 * @return
	 * @throws DataAccessException
	 */
	public Long getCountByNamedParam(final String queryString, final String[] paramNames, final Object[] values)
			throws DataAccessException {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryString);
				for (int i = 0; i < values.length; i++) {
					query.setParameter(paramNames[i], values[i]);
				}
				return query.uniqueResult();
			}
		});
	}

	/**
	 * 使用带命名的参数的HSQL语句检索数据
	 * 
	 * @param queryString
	 * @param paramName
	 * @param value
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedParam(String queryString, String paramName, Object value) throws DataAccessException {
		return getHibernateTemplate().findByNamedParam(queryString, paramName, value);
	}

	/**
	 * 使用带命名的参数的HSQL语句检索数据
	 * 
	 * @param queryString
	 * @param paramNames
	 *            数组
	 * @param values
	 *            数组
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedParam(String queryString, String[] paramNames, Object[] values) throws DataAccessException {
		return getHibernateTemplate().findByNamedParam(queryString, paramNames, values);
	}

	/**
	 * 使用带命名的参数的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @param value
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQuery(String queryName, Object value) throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName, value);
	}

	/**
	 * 使用带命名的参数的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @param values
	 *            数组
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQuery(String queryName, Object[] values) throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName, values);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQuery(String queryName) throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @param paramName
	 * @param value
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
			throws DataAccessException {
		return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramName, value);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @param paramNames
	 * @param values
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
			throws DataAccessException {
		return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 * 
	 * @param queryName
	 * @param valueBean
	 * @return
	 * @throws DataAccessException
	 */
	public List findByNamedQueryAndValueBean(String queryName, Object valueBean) throws DataAccessException {
		return getHibernateTemplate().findByNamedQueryAndValueBean(queryName, valueBean);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 * 
	 * @param queryString
	 * @param valueBean
	 * @return
	 * @throws DataAccessException
	 */
	public List findByValueBean(String queryString, Object valueBean) throws DataAccessException {
		return getHibernateTemplate().findByValueBean(queryString, valueBean);
	}

	/**
	 * 强制立即更新缓冲数据到数据库（否则仅在事务提交时才更新）
	 * 
	 * @throws DataAccessException
	 */
	public void flush() throws DataAccessException {
		getHibernateTemplate().flush();
	}

	/**
	 * 根据主键获取实体并加锁。如果没有相应的实体，返回 null。
	 * 
	 * @param entityClass
	 * @param id
	 * @param lockMode
	 * @return
	 * @throws DataAccessException
	 */
	public Object get(Class entityClass, Serializable id, LockMode lockMode) throws DataAccessException {
		return getHibernateTemplate().get(entityClass, id, lockMode);
	}

	/**
	 * 根据主键获取实体。如果没有相应的实体，返回 null。
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 * @throws DataAccessException
	 */
	public <T> T get(Class<T> entityClass, Serializable id) throws DataAccessException {
		return getHibernateTemplate().get(entityClass, id);
	}

	/**
	 * 根据主键+实体名获取实体并加锁。如果没有相应的实体，返回 null。
	 * 
	 * @param entityName
	 * @param id
	 * @param lockMode
	 * @return
	 * @throws DataAccessException
	 */
	public Object get(String entityName, Serializable id, LockMode lockMode) throws DataAccessException {
		return getHibernateTemplate().get(entityName, id, lockMode);
	}

	/**
	 * 根据主键+实体名获取实体。如果没有相应的实体，返回 null。
	 * 
	 * @param entityName
	 * @param id
	 * @return
	 * @throws DataAccessException
	 */
	public Object get(String entityName, Serializable id) throws DataAccessException {
		return getHibernateTemplate().get(entityName, id);
	}

	/**
	 * 使用HSQL语句检索数据，返回 Iterator
	 * 
	 * @param queryString
	 * @param value
	 * @return
	 * @throws DataAccessException
	 */
	public Iterator iterate(String queryString, Object value) throws DataAccessException {
		return getHibernateTemplate().iterate(queryString, value);
	}

	/**
	 * 使用HSQL语句检索数据，返回 Iterator
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 * @throws DataAccessException
	 */
	public Iterator iterate(String queryString, Object[] values) throws DataAccessException {
		return getHibernateTemplate().iterate(queryString, values);
	}

	/**
	 * 使用HSQL语句检索数据，返回 Iterator
	 * 
	 * @param queryString
	 * @return
	 * @throws DataAccessException
	 */
	public Iterator iterate(String queryString) throws DataAccessException {
		return getHibernateTemplate().iterate(queryString);
	}

	/**
	 * 根据主键获取实体并加锁。如果没有相应的实体，抛出异常
	 * 
	 * @param entityClass
	 * @param id
	 * @param lockMode
	 * @return
	 * @throws DataAccessException
	 */
	public Object load(Class entityClass, Serializable id, LockMode lockMode) throws DataAccessException {
		return getHibernateTemplate().load(entityClass, id, lockMode);
	}

	/**
	 * 根据主键获取实体。如果没有相应的实体，抛出异常
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 * @throws DataAccessException
	 */
	public Object load(Class entityClass, Serializable id) throws DataAccessException {
		return getHibernateTemplate().load(entityClass, id);
	}

	/**
	 * 根据主键获取实体。如果没有相应的实体，抛出异常
	 * 
	 * @param entity
	 * @param id
	 * @throws DataAccessException
	 */
	public void load(Object entity, Serializable id) throws DataAccessException {
		getHibernateTemplate().load(entity, id);
	}

	/**
	 * 根据主键获取实体并加锁。如果没有相应的实体，抛出异常
	 * 
	 * @param entityName
	 * @param id
	 * @param lockMode
	 * @return
	 * @throws DataAccessException
	 */
	public Object load(String entityName, Serializable id, LockMode lockMode) throws DataAccessException {
		return getHibernateTemplate().load(entityName, id, lockMode);
	}

	/**
	 * 根据主键获取实体。如果没有相应的实体，抛出异常
	 * 
	 * @param entityName
	 * @param id
	 * @return
	 * @throws DataAccessException
	 */
	public Object load(String entityName, Serializable id) throws DataAccessException {
		return getHibernateTemplate().load(entityName, id);
	}

	/**
	 * 获取全部实体。如果没有相应的实体，抛出异常
	 * 
	 * @param entityClass
	 * @return
	 * @throws DataAccessException
	 */
	public List loadAll(Class entityClass) throws DataAccessException {
		return getHibernateTemplate().loadAll(entityClass);
	}

	/**
	 * 加锁指定的实体
	 * 
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void lock(Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().lock(entity, lockMode);
	}

	/**
	 * 加锁指定的实体
	 * 
	 * @param entityName
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void lock(String entityName, Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().lock(entityName, entity, lockMode);
	}

	/**
	 * 在同一个identifier copy entity
	 * 
	 * @param entity
	 * @return
	 * @throws DataAccessException
	 */
	public Object merge(Object entity) throws DataAccessException {
		return getHibernateTemplate().merge(entity);
	}

	/**
	 * 在同一个identifier copy entity
	 * 
	 * @param entityName
	 * @param entity
	 * @return
	 * @throws DataAccessException
	 */
	public Object merge(String entityName, Object entity) throws DataAccessException {
		return getHibernateTemplate().merge(entityName, entity);
	}

	/**
	 * Persist the given transient instance.
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void persist(Object entity) throws DataAccessException {
		getHibernateTemplate().persist(entity);
	}

	/**
	 * Persist the given transient instance.
	 * 
	 * @param entityName
	 * @param entity
	 * @throws DataAccessException
	 */
	public void persist(String entityName, Object entity) throws DataAccessException {
		getHibernateTemplate().persist(entityName, entity);
	}

	/**
	 * Re-read the state of the given persistent instance
	 * 
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void refresh(Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().refresh(entity, lockMode);
	}

	/**
	 * Re-read the state of the given persistent instance
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void refresh(Object entity) throws DataAccessException {
		getHibernateTemplate().refresh(entity);
	}

	/**
	 * Persist the state of the given detached instance according to the given replication mode, reusing the current
	 * identifier value.
	 * 
	 * @param entity
	 * @param replicationMode
	 * @throws DataAccessException
	 */
	public void replicate(Object entity, ReplicationMode replicationMode) throws DataAccessException {
		getHibernateTemplate().replicate(entity, replicationMode);
	}

	/**
	 * Persist the state of the given detached instance according to the given replication mode, reusing the current
	 * identifier value.
	 * 
	 * @param entityName
	 * @param entity
	 * @param replicationMode
	 * @throws DataAccessException
	 */
	public void replicate(String entityName, Object entity, ReplicationMode replicationMode) throws DataAccessException {
		getHibernateTemplate().replicate(entityName, entity, replicationMode);
	}

	/**
	 * 保存
	 * 
	 * @param entity
	 * @return
	 * @throws DataAccessException
	 */
	public Long save(Object entity) throws DataAccessException {
		return (Long) getHibernateTemplate().save(entity);
	}

	public void saveDoubleKeyObject(Object entity) throws DataAccessException {
		getHibernateTemplate().save(entity);
	}

	/**
	 * 保存
	 * 
	 * @param entityName
	 * @param entity
	 * @return
	 * @throws DataAccessException
	 */
	public Long save(String entityName, Object entity) throws DataAccessException {
		return (Long) getHibernateTemplate().save(entityName, entity);
	}

	/**
	 * 存在更新，不存在保存
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void saveOrUpdate(Object entity) throws DataAccessException {
		getHibernateTemplate().saveOrUpdate(entity);
	}

	/**
	 * 存在更新，不存在保存
	 * 
	 * @param entityName
	 * @param entity
	 * @throws DataAccessException
	 */
	public void saveOrUpdate(String entityName, Object entity) throws DataAccessException {
		getHibernateTemplate().saveOrUpdate(entityName, entity);
	}

	/**
	 * 存在更新，不存在保存
	 * 
	 * @param entityName
	 * @param entity
	 * @throws DataAccessException
	 */
	public Object saveOrUpdateReturn(Object entity) throws DataAccessException {
		getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}

	/**
	 * 存在,批量更新;不存在,批量保存
	 * 
	 * @param entities
	 * @throws DataAccessException
	 */
	public void saveOrUpdateAll(Collection entities) throws DataAccessException {
		getHibernateTemplate().saveOrUpdateAll(entities);
	}

	/**
	 * 更新并加锁
	 * 
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void update(Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().update(entity, lockMode);
	}

	/**
	 * 更新
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void update(Object entity) throws DataAccessException {
		getHibernateTemplate().update(entity);
	}

	/**
	 * 更新并加锁
	 * 
	 * @param entityName
	 * @param entity
	 * @param lockMode
	 * @throws DataAccessException
	 */
	public void update(String entityName, Object entity, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().update(entityName, entity, lockMode);
	}

	/**
	 * 更新
	 * 
	 * @param entityName
	 * @param entity
	 * @throws DataAccessException
	 */
	public void update(String entityName, Object entity) throws DataAccessException {
		getHibernateTemplate().update(entityName, entity);
	}

	/**
	 * 调用无参数存储过程
	 * 
	 * @param queryName
	 * @return
	 */
	public List callSelectProcedure(final String queryName) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.getNamedQuery(queryName);
				return query.list();
			}
		});
	}
	/**
	 * 参数赋值
	 * 
	 * @param queryObject
	 * @param paramName
	 * @param value
	 * @throws HibernateException
	 */
	@SuppressWarnings("rawtypes")
	protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value)
			throws HibernateException {
		if (value instanceof Collection) {
			queryObject.setParameterList(paramName, (Collection) value);
		} else if (value instanceof Object[]) {
			queryObject.setParameterList(paramName, (Object[]) value);
		} else {
			queryObject.setParameter(paramName, value);
		}
	}

	/**
	 * 根据传入的SQL，返回List，List中放的是Object数组
	 * 
	 * @param sql
	 * @author 范继峰
	 * @return
	 */
	public List findColsBySqlQuery(String sql) {
		List resultList = new ArrayList();
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		resultList = session.createSQLQuery(sql).list();
		session.close();
		return resultList;
	}

	/**
	 * 求传入的QBC查询总记录条数
	 * 
	 * @param criteria
	 *            QBC对象
	 * @return
	 */
	public int getTotalSizeForCriteria(DetachedCriteria criteria) {
		// 获取根据条件分页查询的总行数
		int totalSize = 0;
		criteria.setProjection(Projections.rowCount());
		List list = this.findByCriteria(criteria);
		if (list.isEmpty()) {
			return totalSize;
		} else {
			totalSize = Integer.parseInt(list.get(0).toString());
		}
		criteria.setProjection(null);// 清除count函数
		return totalSize;
	}
}
